package com.chengqs.rapid.core.netty.processor.filter.route;

import com.chengqs.rapid.common.constants.ProcessorFilterConstants;
import com.chengqs.rapid.common.enums.ResponseCode;
import com.chengqs.rapid.common.exception.RapidConnectException;
import com.chengqs.rapid.common.exception.RapidResponseException;
import com.chengqs.rapid.common.util.TimeUtil;
import com.chengqs.rapid.core.RapidConfigLoader;
import com.chengqs.rapid.core.context.Context;
import com.chengqs.rapid.core.context.RapidContext;
import com.chengqs.rapid.core.context.RapidResponse;
import com.chengqs.rapid.core.helper.AsyncHttpHelper;
import com.chengqs.rapid.core.netty.processor.filter.AbstractEntryProcessorFilter;
import com.chengqs.rapid.core.netty.processor.filter.Filter;
import com.chengqs.rapid.core.netty.processor.filter.FilterConfig;
import com.chengqs.rapid.core.netty.processor.filter.ProcessorFilterType;
import lombok.extern.slf4j.Slf4j;
import org.asynchttpclient.Request;
import org.asynchttpclient.Response;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * <B>主类名称：</B>HttpRouteFilter<BR>
 * <B>概要说明：</B>请求路由的中置过滤器<BR>
 *
 * @author: chengqs
 * @create: 2025-03-17 18:39:51
 **/
@Filter(
        id = ProcessorFilterConstants.HTTP_ROUTE_FILTER_ID,
        name = ProcessorFilterConstants.HTTP_ROUTE_FILTER_NAME,
        value = ProcessorFilterType.ROUTE,
        order = ProcessorFilterConstants.HTTP_ROUTE_FILTER_ORDER
)
@Slf4j
public class HttpRouteFilter extends AbstractEntryProcessorFilter<FilterConfig> {

    public HttpRouteFilter() {
        super(FilterConfig.class);
    }

    @Override
    public void entry(Context context, Object... args) throws Throwable {
        RapidContext rapidContext = (RapidContext) context;
        Request request = rapidContext.getRequestMutable().build();

        // 设置RS：
        rapidContext.setSRTime(TimeUtil.currentTimeMillis());

        CompletableFuture<Response> future = AsyncHttpHelper.getInstance().executeRequest(request);

        // 双异步和单异步模式
        boolean whenComplete = RapidConfigLoader.getRapidConfig().isWhenComplete();
        if (whenComplete) {
            // 单异步
            future.whenComplete((response, throwable) -> {
                complete(request, response, throwable, rapidContext, args);
            });
        } else {
            // 双异步
            future.whenCompleteAsync((response, throwable) -> {
                complete(request, response, throwable, rapidContext, args);
            });
        }
    }

    /**
     * 真正执行请求响应回来的操作方法
     *
     * @param request
     * @param response
     * @param throwable
     * @param rapidContext
     * @param args
     */
    private void complete(Request request,
                          Response response,
                          Throwable throwable,
                          RapidContext rapidContext,
                          Object... args) {
        try {
            // 设置RR
            rapidContext.setRRTime(TimeUtil.currentTimeMillis());

            // 1. 释放请求资源
            rapidContext.releaseRequest();
            // 2. 判断是否有异常
            if (Objects.nonNull(throwable)) {
                String url = request.getUrl();
                if (throwable instanceof java.util.concurrent.TimeoutException) {
                    // 超时异常
                    log.warn("HttpRouteFilter#complete() 返回响应执行， 请求路径：{}，耗时超过 {}  ms.",
                            url,
                            (request.getRequestTimeout() == 0 ?
                                    RapidConfigLoader.getRapidConfig().getHttpRequestTimeout() :
                                    request.getRequestTimeout())
                    );
                    // 网关里设置异常都是使用自定义异常
                    rapidContext.setThrowable(new RapidResponseException(ResponseCode.REQUEST_TIMEOUT));
                } else {
                    // 其他异常情况
                    rapidContext.setThrowable(new RapidConnectException(throwable,
                            rapidContext.getUniqueId(),
                            url,
                            ResponseCode.HTTP_RESPONSE_ERROR));
                }
            } else {
                // 正常返回响应结果：
                // 设置响应信息
                rapidContext.setResponse(RapidResponse.buildRapidResponse(response));
            }
        } catch (Throwable t) {
            // 最终兜底异常处理
            rapidContext.setThrowable(new RapidResponseException(ResponseCode.INTERNAL_ERROR));
            log.error("HttpRouteFilter#complete() catch到未知异常", t);
        } finally {
            try {
                // 1. 设置写回标记
                rapidContext.written();
                // 2. 让异步线程内部自己进行触发下一个节点执行
                super.fireNext(rapidContext, args);
            } catch (Throwable t) {
                // 兜底处理，把异常信息放入上下文
                rapidContext.setThrowable(new RapidResponseException(ResponseCode.INTERNAL_ERROR));
                log.error("HttpRouteFilter#fireNext() 出现异常", t);
            }
        }
    }
}
